package top.go2do.common.filter;

import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWT;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import top.go2do.common.module.UserInfoBO;
import top.go2do.common.resolver.TokenUserInfoHandler;
import top.go2do.common.threadLocal.UserInfoContext;
import top.go2do.common.utils.JwtUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @Description 通过Spring的OncePerRequestFilter，保证一个请求校验一次token
 * @Author xingyj
 * @CreateTime 2025/3/25 12:50
 */
@Slf4j
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "custom.token.filter")
public class TokenFilter extends OncePerRequestFilter {

    private List<String> whiteList;

    private String headerKey;

    private static final String TOKEN_PREFIX = "Bearer ";

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private TokenUserInfoHandler tokenUserInfoHandler;

    @Override
    public void doFilterInternal(HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain filterChain)
            throws IOException, ServletException {

        String requestURI = httpRequest.getRequestURI();
        String requestMethod = httpRequest.getMethod();
        // 检查是否在白名单中
        if (HttpMethod.OPTIONS.name().equals(requestMethod) || (whiteList != null && whiteList.contains(requestURI))) {
            filterChain.doFilter(httpRequest, httpResponse);
            return;
        }

        // 检查请求头中是否包含 token
        String token = httpRequest.getHeader(headerKey);
        if (token == null || token.isEmpty()) {
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.getWriter().write("no auth token");
            return;
        }

        if (!token.startsWith("Bearer ")) {
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.getWriter().write("auth token invalid");
            return;
        }
        String coreToken = token.substring(7);

        if (!jwtUtils.checkToken(coreToken)) {
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.getWriter().write("auth token invalid");
            return;
        }
        JWT jwt = jwtUtils.parseToken(coreToken);
        JSONObject payload = jwt.getPayloads();
        Long userId = payload.getLong(JwtUtils.KEY_USER_ID);
        // DONE：根据userID 查询用户信息（redis+mysql）
        UserInfoBO userInfoBO = tokenUserInfoHandler.getUserInfoByUserId(userId);

        UserInfoContext.set(userInfoBO);
        try {
            // 继续处理请求
            filterChain.doFilter(httpRequest, httpResponse);
        } finally {
            UserInfoContext.remove();
        }
    }
}
